﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "SteppedViewSymbol.h"

#include "NdbObjectSchematic.h"
#include "DbObjectUtils.h"
#include "OwnerPtr.h"
#include "IGenericElement.h"
#include "IElementBasicInformation.h"
#include "GbmpBuiltInCategoryUniIdentitiesNew.h"
#include "IElementParentReporter.h"
#include "IGraphicsElementShape.h"
#include "IModelView.h"
#include "IViewClipRange.h"
#include "ISteppedSectionPlane.h"
#include "IDocument.h"
#include "Vector3d.h"
#include "AlgorithmProject.h"
#include "IPlane.h"
#include "IGraphicsLine.h"
#include "IGraphicsText.h"
#include "Vector3dUtils.h"
#include "AnchorAlignmentType.h"
#include "TextPrimitiveType.h"
#include "AlgorithmMinimalDistance.h"
#include "Vector2dUtils.h"
#include "MathUtils.h"
#include "IModelViewEventArgs.h"
#include "IModelViewEvent.h"
#include "IRegeneratorDataIdCreator.h"
#include "IRegenerator.h"
#include "IElementParameters.h"
#include "IGraphicsStyleManager.h"
#include "GbmpModelViewUtil.h"
#include "ImplementationUidTreeRegister.h"
#include "NdbUpgrade.h"
#include "NdbDocUpgradeManager.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"


using namespace gcmp;

//const double SectionViewSymbolLongLineLength = 1000;
//const double SectionViewSymbolShortLineLength = 600;
//const double SteppedViewSymbolFontsHeight = 514;  //由于GText替换为GTextEx后会导致字形显示变大，此处为了基本达到原有的大小*0.735,700*0.735,此处的0.735为经验值
//IMPLEMENT_REGEN_FUNCTIONS(gcmp, SteppedViewSymbol, SectionViewCoord)


IMPLEMENT_REGEN_FUNCTIONS(gcmp, SteppedViewSymbol, ModelViewRangeUpdated)

DBOBJECT_DATA_DEFINE(SteppedViewSymbol)
{
    m_pOwnerElement = nullptr;
    SetStairViewId__(ElementId::InvalidID);
    //SetMarkChanged__(true);
}

ISteppedViewSymbol* SteppedViewSymbol::Create(IDocument* pDoc, const ElementId& idModelView, const ElementId& idStairView)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"invalid pDoc",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(idStairView.IsValid(), L"invalid sectionModelViewId",L"GDMPLab",L"2024-03-30");
    OwnerPtr<SteppedViewSymbol> opSymbol = NEW_AS_OWNER_PTR(SteppedViewSymbol);
    SteppedViewSymbol* pSymbol = opSymbol.get();

    IGenericElement* pGenericElement = IGenericElement::Create(pDoc, TransferOwnership(opSymbol), SteppedViewSymbol::GetClassId().GetGuid());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pGenericElement, L"invalid pGenericElement",L"GDMPLab",L"2024-03-30");

    //pGenericElement->SetPositionPoints(NEW_AS_OWNER_PTR(SteppedViewSymbolPositionPoints));
    //if (pGenericElement->GetElementParameters())
    //    pGenericElement->GetElementParameters()->SetElementParametersCustomizer(NEW_AS_OWNER_PTR(SteppedViewSymbolParametersCustomizer));
    //pGenericElement->SetElementTransformationComponent(NEW_AS_OWNER_PTR(SteppedViewSymbolTransformationComponent));
    //pGenericElement->SetViewSpecificShapeComponent(NEW_AS_OWNER_PTR(SteppedViewSymbolViewSpecificShapeComponent));
    //pGenericElement->SetElementCopyStrategyComponent(NEW_AS_OWNER_PTR(SteppedViewSymbolCopyStrategyComponent));
    //pGenericElement->SetElementCopyPasteComponent(NEW_AS_OWNER_PTR(SteppedViewSymbolCopyPasteComponent));
    //pGenericElement->SetElementRegenerationComponent(NEW_AS_OWNER_PTR(SteppedViewSymbolRegenerationBehavior));
    
    IElementBasicInformation* pBasicInfo = pGenericElement->GetBasicInformation();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pBasicInfo, L"invalid pBasicInfo",L"GDMPLab",L"2024-03-30");
    pBasicInfo->SetCategoryUid(BuiltInCategoryUniIdentities::BICU_STAIR_VIEW_SYMBOL);
    pBasicInfo->SetDefaultTypeName(GBMP_TR(L"阶梯面视图"));
    pBasicInfo->SetImplementationUid(SteppedViewSymbol::GetImplementationUid());

    pSymbol->SetStairViewId(idStairView);
    pSymbol->SetModelViewId(idModelView);

    IModelView* pStairModelView = quick_cast<IModelView>(pDoc->GetElement(idStairView));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pStairModelView, L"invalid pSectionModelView",L"GDMPLab",L"2024-03-30");
    pStairModelView->SetViewSymbolId(pGenericElement->GetElementId());

    //Coordinate3d coord(pStairModelView->GetOrigin(), pStairModelView->GetRightDirection(), pStairModelView->GetUpDirection());
    //OwnerPtr<IGraphicsStairPlane> opStairPlane = IGraphicsStairPlane::Create(stStairLine,coord);
    //pSymbol->SetStairPlane__(TransferOwnership(opStairPlane));

    
    
    return quick_cast<ISteppedViewSymbol>(pGenericElement->GetExternalObject());
}

#pragma region IExternalObject 接口
bool SteppedViewSymbol::SetOwnerElement(IElement* pOwnerElement)
{
    m_pOwnerElement = pOwnerElement;
    return true;
}

const IElement* SteppedViewSymbol::GetOwnerElement() const
{
    return m_pOwnerElement;
}

IElement* SteppedViewSymbol::GetOwnerElement()
{
    return m_pOwnerElement;
}

NdbObject* SteppedViewSymbol::GetTopOwnerObject() const
{
    return quick_cast<NdbObject>(const_cast<IElement*>(GetOwnerElement()));
}

void SteppedViewSymbol::UpdateForWeakParentDeletion(const std::set<ElementId>& deletedElementIds)
{
}

void SteppedViewSymbol::ReportParents(IElementParentReporter& reporter) const
{
    reporter.ReportStrong(GetStairViewId());
    
    reporter.ReportWeak(GetModelViewId());
}

bool SteppedViewSymbol::FinishEditing()
{
    return true;
}
#pragma endregion IExternalObject 接口

#pragma region ISteppedViewSymbol 接口
ElementId SteppedViewSymbol::GetModelViewId() const
{
    return GetModelViewId__();
}
ElementId SteppedViewSymbol::GetStairViewId() const
{
    return GetStairViewId__();
}
const ISteppedSectionPlane* SteppedViewSymbol::GetSteppedPlane() const
{
    const IModelView* pModelView = GetSteppedView();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pModelView, L"pModelView为空。",L"GDMPLab",L"2024-03-30");
    const IDocument* pDoc = GetDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空。",L"GDMPLab",L"2024-03-30");
    IElement* pElement = pDoc->GetElement(pModelView->GetCompositeSectionPlaneId());
    return quick_cast<ISteppedSectionPlane>(pElement);
}
ISteppedSectionPlane* SteppedViewSymbol::GetSteppedPlane()
{
    const IModelView* pModelView = GetSteppedView();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pModelView, L"pModelView为空。",L"GDMPLab",L"2024-03-30");
    const IDocument* pDoc = GetDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空。",L"GDMPLab",L"2024-03-30");
    IElement* pElement = pDoc->GetElement(pModelView->GetCompositeSectionPlaneId());
    return quick_cast<ISteppedSectionPlane>(pElement);
}
ElementId SteppedViewSymbol::GetOwnerElementId() const
{
    if (!m_pOwnerElement)
    {
        return ElementId::InvalidID;
    }
    return m_pOwnerElement->GetElementId();
}

std::vector<gcmp::ElementId> SteppedViewSymbol::CreateAuxiliaryElements(gcmp::IModelView* pModelView) const
{
    return std::vector<ElementId>();
}




gcmp::UniIdentity gcmp::SteppedViewSymbol::GetImplementationUid()
{
    static UniIdentity s_implementationUid = UniIdentity::Create(
        GuidUtils::FromString(L"{1A274312-C397-4A60-B708-1FCA661E31FA}"), L"SteppedViewSymbol");
    return s_implementationUid;
}


OwnerPtr<IGraphicsElementShape> SteppedViewSymbol::CreateModelViewElementShape(const IModelView* pModelView) const
{
    const ISteppedSectionPlane* pStairPlane = GetSteppedPlane();

    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pStairPlane, L"invalid pStairLine",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pModelView, L"invalid pModelView",L"GDMPLab",L"2024-03-30");

    OwnerPtr<IGraphicsElementShape> opGrep = IGraphicsElementShape::Create(GraphicsRenderLayer::Annotation);
    //获取Doc
    IDocument* pDoc = pModelView->GetDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"invalid pDoc",L"GDMPLab",L"2024-03-30");
    ElementId idSymbolStyle;
    IGraphicsStyleManager* pStyleManager = pDoc->GetGraphicsStyleManager();
    if (pStyleManager)
    {
        idSymbolStyle = pStyleManager->GetGraphicsStyleIdByCategoryUid(BuiltInCategoryUniIdentities::BICU_SECTION_VIEW_SYMBOL);
    }

    auto funAddLine = [&idSymbolStyle, &opGrep](const Vector3d& ptStart, const Vector3d& ptEnd)
    {
        OwnerPtr<IGraphicsLine> opLine = IGraphicsLine::Create(ptStart, ptEnd);
        opLine->SetGraphicsStyleId(idSymbolStyle);
        opGrep->AddChild(TransferOwnership(opLine));
    };

    std::list<Vector3d> sectionLinePoints = pStairPlane->GetSectionLine();

    auto& iterLine = sectionLinePoints.begin();
    Vector3d ptLineStart = *iterLine++;
    while (iterLine != sectionLinePoints.end())
    {
        Vector3d ptLineEnd = *iterLine++;

        funAddLine(ptLineStart, ptLineEnd);
        ptLineStart = ptLineEnd;
    }
    const IModelView* pStairModelView = GetSteppedView();
    SteppedLineStruct stStairLine = pStairPlane->GetSteppedLine();
    OwnerPtr<IGraphicsText> opNameText = IGraphicsText::Create(L"", stStairLine.StartPoint, stStairLine.SectionDirection, -pModelView->GetViewDirection(), 514,
        pStairModelView->GetName(), AnchorAlignmentType::LeftTop);
    opNameText->SetTextPrimitiveType(TextPrimitiveType::Triangle);
    if (pStyleManager)
    {
        opNameText->SetGraphicsStyleId(pStyleManager->GetGraphicsStyleIdByCategoryUid(
            BuiltInCategoryUniIdentities::BICU_STAIR_VIEW_SYMBOL));
        opGrep->AddChild(TransferOwnership(opNameText));
    }

    opGrep->SetIsClippable(false);
    return opGrep;
}
 
bool SteppedViewSymbol::MakeTransform(const Matrix4d& matrix)
{
    ISteppedSectionPlane* pStairPlane = GetSteppedPlane();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pStairPlane, L"invalid pStairPlane",L"GDMPLab",L"2024-03-30");
    pStairPlane->Transform(matrix);

    ResetSteppedView(pStairPlane);

    MarkChanged();

    return true;
}
void SteppedViewSymbol::ResetSteppedView(const ISteppedSectionPlane* pSteppedPlane)
{
}
void SteppedViewSymbol::MarkChanged()
{
    //SetMarkChanged__(!GetMarkChanged__());
}

IDocument* SteppedViewSymbol::GetDocument() const
{
    if (!m_pOwnerElement)
    {
        return nullptr;
    }
    return m_pOwnerElement->GetDocument();
}

IModelView* SteppedViewSymbol::GetSteppedView() const
{
    IDocument* pDoc = GetDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"invalid pDoc",L"GDMPLab",L"2024-03-30");
    return quick_cast<IModelView>(pDoc->GetElement(GetStairViewId__()));
}

void SteppedViewSymbol::SetModelViewId(const ElementId& viewId)
{
    SetModelViewId__(viewId);
}

IModelView* SteppedViewSymbol::GetModelView() const
{
    IDocument* pDoc = GetDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"invalid pDoc",L"GDMPLab",L"2024-03-30");
    return quick_cast<IModelView>(pDoc->GetElement(GetModelViewId__()));
}

void SteppedViewSymbol::SetStairViewId(const ElementId& viewId)
{
    SetStairViewId__(viewId);
}


REGISTER_IMPLEMENTATION_UID_TREE_RELATION(IGenericElement, SteppedViewSymbol);

